/**
 * Copyright 2014 wasu.com
 *
 *
 * Create on 2015年7月9日 下午8:18:52
 */
package xiaojian.toolkit.handler.actor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import xiaojian.toolkit.ebus.EventBus;
import xiaojian.toolkit.ebus.actors.AbstractEventActor;
import xiaojian.toolkit.ebus.annotation.HandleEvents;
import xiaojian.toolkit.ebus.annotation.HandleEventsClazz;
import xiaojian.toolkit.handler.ReqHandler;
import xiaojian.toolkit.util.ClosureEx;

/**
 * 容器装载bean的时候，检查bean是否为reqhandler，如果是的话，提取该reqhandler能够处理的事件并且注册到ebus。
 * 
 * @author <a href="mailto:caoxiaojian@wasu.cn">xiaojiancao</a>
 *
 */
public class AutoAssembleReqHandlerActor extends AbstractEventActor implements
		BeanPostProcessor {

	private static Logger logger = LoggerFactory
			.getLogger(AutoAssembleReqHandlerActor.class);

	private List<Runnable> dtors = new ArrayList<Runnable>();
	private Map<String, ClosureEx> closures = new HashMap<String, ClosureEx>();

	public AutoAssembleReqHandlerActor(EventBus ebus, String name) {
		super(ebus, name);
	}

	/**
	 * 在bean初始化之前。
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		return bean;
	}

	/**
	 * bean初始化之后。
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {

		if (!(bean instanceof ReqHandler)) {
			return bean;
		}

		ReqHandler reqHandler = (ReqHandler) bean;
		HandleEvents handleEvents = reqHandler.getClass().getAnnotation(
				HandleEvents.class);
		
		HandleEventsClazz handleEventsClazz = reqHandler.getClass().getAnnotation(HandleEventsClazz.class);
		
		
		if (handleEvents == null || handleEventsClazz == null) {
			return bean;
		}

		if (StringUtils.isEmpty(handleEvents.value()) 
				&& (handleEventsClazz.eventClazz() == null 
					|| handleEventsClazz.eventClazz().length == 0)) {
			logger.warn(
					"BeanName[{}], ReqHandler[{}], event is null or empty.",
					beanName, reqHandler);
			return bean;
		}

		String[] events = StringUtils.split(handleEvents.value(), ",");
		for (String event : events) {
			ReqHandlerFunctor functor = new ReqHandlerFunctor(reqHandler);
			this.closures.put(event, functor);
			dtors.add(registerObserver(event, functor));

			logger.debug("Add event[" + event + "] <-> reqHandler["
					+ reqHandler + "].");
		}
		
		Class[] eventsClazz = handleEventsClazz.eventClazz();
		for (Class clazz : eventsClazz) {
			ReqHandlerFunctor functor = new ReqHandlerFunctor(reqHandler);
			this.closures.put("event." + clazz.getName(), functor);
			dtors.add(registerObserver("event." + clazz.getName(), functor));

			logger.debug("Add event[" + "event." + clazz.getName() + "] <-> reqHandler["
					+ reqHandler + "].");
		
		}
		
		return bean;
	}

	public void destroy() {
		for (Runnable canceler : dtors) {
			try {
				canceler.run();
			} catch (Exception e) {
				logger.error("destroy:", e);
			}
		}
		dtors.clear();

		super.destroy();
	}

}
